<?php
 /*
  * @Descripttion: 
  * @version: v1
  * @Author: Terry
  * @Date: 2021-02-19 18:07:16
 * @LastEditors: Terry
 * @LastEditTime: 2024-11-05 21:22:12
  */
namespace libs;

use OSS\OssClient;
use OSS\Core\OssException;
use OSS\Core\OssUtil;
// use OSS\Model\ServerSideEncryptionConfig;

class ALiOss{
    private $client;
    //旧oss账号
    // private $accessKeyId = "LTAI5t92HhVyA4mPBjEkwwf5";
    // private $accessKeySecret = "omNFnuN69o1a6wKnWm5e7u4Rf3sCAT";
    
    //y200sc auxface-oss
    private $accessKeyId;
    private $accessKeySecret;
    private $endpoint;
    private $bucket;
    private $ossClient;
    private $path;
    private $ext;
    private $object;

    
    /**
     * @description: 构建方法
     * @Author: Terry
     * @Date: 2022-03-16 18:52:49
     * @param {*} $path 上传到oss的文件名称
     * @param {*} $ext上传到oss的文件后缀
     */    
    public function __construct($path='',$ext=''){
        $this->path = $path;
        $this->ext = $ext;
        $this->object = $path.'.'.$ext;
        $this->endpoint = env('oss.aliEndpoint');
        $this->bucket = env('oss.aliBucket');
        $this->accessKeyId = env('oss.accessKeyId');
        $this->accessKeySecret = env('oss.accessKeySecret');

        $this->ossClient = new OssClient($this->accessKeyId, $this->accessKeySecret, $this->endpoint);
    }

    /**
     * @description: 文件直接上传
     * @Author: Terry
     * @Date: 2022-03-16 18:52:49
     * @param {*} $file 需要上传的文件路径
     */    
    public function upload($file){
        try{
              // 将Bucket默认的服务器端加密方式设置为OSS完全托管加密（SSE-OSS）。
            // $config = new ServerSideEncryptionConfig("AES256");
            // $this->ossClient->putBucketEncryption($this->bucket, $config);
            if(is_file($file)){
                clearstatcache();
                $res =  $this->ossClient->uploadFile($this->bucket, $this->object, $file);
                $url = str_replace('http://','https://',$res['oss-request-url']); 
                unlink($file);
                return str_replace('-internal','',$res['oss-request-url']);
            }
            return false;
        } catch(OssException $e) {
            dump($e->getMessage());
            return false;
        }
    }
// ================================================大文件上传:begin====================================================
    /**
     * @Descripttion: 获取oss唯一识别号
     * @Author: Terry
     * @Date: 2022-01-27 21:16:09
     * @param {*} $path 
     */
    public function getFileId(){
        $filePath = $this->path.'/uploadId.txt';
        if(is_file($filePath)) $uploadId = file_get_contents($filePath);
        if(empty($uploadId)){
            $uploadId =  $this->ossClient->initiateMultipartUpload($this->bucket, $this->object);
            if(empty($uploadId)) return false;
            if(!is_dir($this->path)) mkdir($this->path,0777,true);
            file_put_contents($filePath,$uploadId);
        }
        return $uploadId;
     }

     /**
      * @Descripttion:  上传分片
      * @Author: Terry
      * @Date: 2022-01-28 12:30:09
      * @param {*} $file 需要上传的文件
      * @param {*} $number 第几个文件
      * @param {*} $total 共几个文件
      * @param {*} $currentChunkSize 本次文件大小
      * @param {*} $chunkSize 多大分一次片
      */ 
     public function uploadPart($file,$number,$total,$currentChunkSize,$chunkSize){
         
        $uploadId = $this->getFileId();
        //文件起始大小
        $seekTo = ($number - 1 ) * $chunkSize;
        // $fileName = "uploads/0f3c2d5fea61c776da3be622227e5a01.mp4";
        $upOptions = [
            // 上传文件。
            $this->ossClient::OSS_FILE_UPLOAD => $file,
            // 设置分片号。
            $this->ossClient::OSS_PART_NUM => (int)$number,
            // 指定分片上传起始位置。
            $this->ossClient::OSS_SEEK_TO => 0,
            // 指定文件长度。
            $this->ossClient::OSS_LENGTH => (int)$currentChunkSize,
            // 是否开启MD5校验，true为开启。
            $this->ossClient::OSS_CHECK_MD5 => false,
        ];
        try {
            $parts = $this->ossClient->uploadPart($this->bucket,$this->object,$uploadId,$upOptions);
            if(!is_dir($this->path)) mkdir($this->path,0777,true);
            $filePath = $this->path.'/uploaded.txt';
            $partsPath = $this->path.'/uploadParts.txt';
            file_put_contents($filePath,$number.',',FILE_APPEND);
            file_put_contents($partsPath,$parts.',',FILE_APPEND);
            return true;
        } catch(OssException $e) {
            return false;
        }
     }

     /**
      * @Descripttion: 文件合并
      * @Author: Terry
      * @Date: 2022-01-27 22:19:53
      * @param {*} $uploadId
      */     
     public function fileMerge(){
        $uploadId = $this->getFileId();
        $uploadParts = $this->getParts();
        if( empty($uploadParts) || empty( $uploadId ) ) return false;
        try {
            $res = $this->ossClient->completeMultipartUpload($this->bucket, $this->object, $uploadId, $uploadParts);
            $partsPath = $this->path.'/url.txt';
            $url  ='https://auxface.oss-cn-guangzhou.aliyuncs.com/' . $this->object;
            file_put_contents($partsPath,$url);
            return $url;
        } catch(OssException $e) {
            return false;
        }
     }

     /**
      * @Descripttion: 获取文件碎片
      * @Author: Terry
      * @Date: 2022-01-27 22:20:10
      * @param {*}
      */
     public function getParts(){
        $list = [];
        $filePath = $this->path.'/uploadParts.txt';
        if(is_file($filePath)){
            $parts  = file_get_contents($filePath);
            $parts = explode(',',$parts);
            foreach ($parts as $key => $value){
                if($value !=''){
                    $list[] = [
                        'PartNumber' => $key + 1,
                        'ETag' => trim($value),
                    ];
                }
            }
        } 
        return $list;
    }
    // ================================================大文件上传：end====================================================
     // ================================================获取oss中的文件列表：begin====================================================
     /**
      * @Description: 获取oss目录路径
      * @Author: Terry
      * @Date: 2023-05-15 17:15:48
      * @param {*} $options         
      *  $options = [
      *      'prefix'=>$file, '前缀 必须/结尾 例如：train/ 或者 /'
      *      'delimiter'=>'/' /为当前目录 。空为下面的所有子目录
      *  ];
      */     
     public function getList($options){
         try {
             $listObjectInfo = $this->ossClient->listObjects($this->bucket, $options);
         } catch (OssException $e) {
             printf($e->getMessage() . "\n");
             return;
         }
         
         //获取所有文件夹
        $prefixList = $listObjectInfo->getPrefixList();
        //获取所有文件
        $objectList = $listObjectInfo->getObjectList();
        if (!empty($prefixList)) {
            foreach ($prefixList as $prefixInfo) {
                $data[] = $prefixInfo->getPrefix();
            }
        }
         if (!empty($objectList)) {
             foreach ($objectList as $objectInfo) {
                 $objectItem = $objectInfo->getKey();
                 //如果后缀为.mp4的加入数组  可延伸类型例如pdf .exe 等
                if(strstr($objectItem,'.mp4')) $data[] = $objectItem;
             }
         }
        return $data ?? false;
     }
     // ================================================获取oss中的文件列表：end====================================================
     // ================================================下载oss中的文件：begin====================================================
     /**
      * @Description: 获取oss目录路径
      * @Author: Terry
      * @Date: 2023-05-15 17:15:48
      * @param {*} $options         
      *  $options = [
      *      'prefix'=>$file, '前缀 必须/结尾 例如：train/ 或者 /'
      *      'delimiter'=>'/' /为当前目录 。空为下面的所有子目录
      *  ];
      */     
     public function download($fileName,$filePath){
        $options = [
            OssClient::OSS_FILE_DOWNLOAD => $filePath
        ];
        $filePath = explode('/',$filePath);
        $file = array_pop($filePath);
        $filePath = join('/',$filePath);
        // 使用try catch捕获异常。如果捕获到异常，则说明下载失败；如果没有捕获到异常，则说明下载成功。
        try{
            makeDir($filePath);
            $this->ossClient->getObject($this->bucket, $fileName, $options);
        } catch(OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        return $filePath .'/'.$file;
     }
     // ================================================下载oss中的文件：end====================================================
 }
 
